﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

using mvcForum.Core;
using mvcForum.Core.Abstractions.Interfaces;
using mvcForum.Core.Events;
using mvcForum.Core.Interfaces.Search;
using mvcForum.Web.Attributes;
using mvcForum.Web.Controllers;
using mvcForum.Web.Extensions;
using mvcForum.Web.Helpers;
using mvcForum.Web.ViewModels;
using mvcForum.Web.ViewModels.Create;
using mvcForum.Web.ViewModels.Delete;
using mvcForum.Web.ViewModels.Update;
using mvcForum.Core.Interfaces.Services;
using mvcForum.Web.Interfaces;
using mvcForum.Core.Interfaces.Events;
using mvcForum.Core.Interfaces.Data;

namespace mvcForum.Web.Areas.Forum.Controllers {

	/// <summary>
	/// Message controller.
	/// The controller handles creating, updating and deleting posts. The controller also handles reporting posts.
	/// </summary>
	public class MessageController : ThemedForumBaseController {
		private readonly IConfiguration config;
		private readonly IIndexer indexer;
		private readonly IEventPublisher eventPublisher;
		public readonly IPostService postService;
		private readonly IAttachmentService attachmentService;

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="appContext">Injected IApplicationContext instance.</param>
		public MessageController(IWebUserProvider userProvider, IContext context, IConfiguration config, IIndexer indexer, IEventPublisher eventPublisher, IAttachmentService attachmentService, IPostService postService)
			: base(userProvider, context) {

			// Store the configuration instance as a variable on the controller instance.
			this.config = config;
			this.indexer = indexer;
			this.eventPublisher = eventPublisher;
			this.attachmentService = attachmentService;
			this.postService = postService;
		}

		#region Create
		[Authorize]
		public ActionResult Create(Int32 id, Int32? replyToId) {
			// Let's get the topic the post should be added to.
			Topic topic = this.GetRepository<Topic>().Read(id);
			// Does the user have access to posting in the forum?
			if (topic.Forum.HasAccess(AccessFlag.Post)) {
				Post replyToMessage = null;
				// Is this a reply to an existing post or just another post as a reply to the topic?
				if (replyToId.HasValue && replyToId.Value > 0) {
					// Reply to a post, let's get the post!
					replyToMessage = this.GetRepository<Post>().Read(replyToId.Value);
				}
				// Let's create the model, we need to show it to the user in a bit!
				var model = new CreateMessageViewModel { TopicId = topic.Id, Topic = new TopicViewModel(topic, new MessageViewModel[] { }, 0, config.MessagesPerPage, false, this.config.AllowQuickReply, this.config.AuthorNameSetting), Posts = new List<MessageViewModel>(), CanUpload = topic.Forum.HasAccess(AccessFlag.Upload) };
				// The post title will be the original topic title prefixed with "Re: " (TODO: localise?)
				model.Subject = String.Format("Re: {0}", topic.Title);

				// Should we show older posts?
				if (this.config.ShowOldPostsOnReply) {
					// Yeah, so let's get all the posts on the topic, and let's get the latest first!
					IEnumerable<Post> messages = topic.Posts.Visible(this.config).OrderByDescending(p => p.Posted);
					// Should we limit the number of posts?
					if (this.config.PostsOnReply > 0) {
						// Yes, so let's limit the number of posts.
						messages = messages.Take(this.config.PostsOnReply);
					}
					foreach (Post p in messages) {
						model.Posts.Add(new MessageViewModel(p, this.config.AuthorNameSetting));
					}
				}

				// Is this a reply to another post?
				if (replyToMessage != null && replyToMessage.Topic.Id == topic.Id) {
					model.ReplyTo = replyToMessage.Id;
					// Let's wrap the text of the original post in BBCode (TODO: Make this an option???)
					model.Body = ForumHelper.Quote(replyToMessage.AuthorName, replyToMessage.Body);
					// The post title will be the original post title prefixed with "Re: " (TODO: localise?)
					model.Subject = String.Format("Re: {0}", replyToMessage.Subject);
				}
				model.Path = new Dictionary<string, string>();
				// Let's create the breadcrumb path!
				HomeController.BuildPath(topic, model.Path, this.Url);
				model.Path.Add("/", "New reply");

				return View(model);
			}

			// Ups, the user is not allowed to post new messages, let him know!
			TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.ForumPosting", new { Name = topic.Forum.Name }));
			// Let's go to the "no access" page!
			return RedirectToRoute("NoAccess");
		}

		[HttpPost]
		[Authorize]
		[NotBanned]
		// TODO: Remove this and get it working with AllowHtml instead!!
		[ValidateInput(false)]
		public ActionResult Create(CreateMessageViewModel newMessage, HttpPostedFileBase[] files) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			// Get the parent topic!
			Topic topic = this.GetRepository<Topic>().Read(newMessage.TopicId);

			// Valid post?
			if (ModelState.IsValid) {
				// Can user post?
				if (topic.Forum.HasAccess(AccessFlag.Post)) {
					Post replyTo = null;
					// Is this a reply to an existing post?
					if (newMessage.ReplyTo.HasValue) {
						// This is a reply to an existing post yes!
						replyTo = this.context.GetRepository<Post>().Read(newMessage.ReplyTo.Value);
					}

					List<String> feedback = new List<String>();
					Post post = this.postService.Create(
														this.ActiveUser,
														topic,
														newMessage.Subject,
														newMessage.Body,
														Request.UserHostAddress,
														Request.UserAgent,
														Url.RouteUrl("ShowTopic", new { id = topic.Id, area = "forum", title = topic.Title.ToSlug() }),
														feedback,
														replyTo
													);

					if (post != null) {
						AccessFlag flag = topic.Forum.GetAccess();
						// Can attach file(s)?
						if ((flag & AccessFlag.Upload) == AccessFlag.Upload) {
							// Any file(s) uploaded directly on the create post page?
							if (files != null && files.Length > 0 /*&& this.config.InlineUpload*/) {

								foreach (HttpPostedFileBase file in files) {
									if (file != null) {
										AttachStatusCode returnValue = this.attachmentService.AttachFile(this.ActiveUser, post, file.FileName, file.ContentType, file.ContentLength, file.InputStream);
										if (returnValue != AttachStatusCode.Success) {
											feedback.Add(ForumHelper.GetString(returnValue.ToString(), new { File = file.FileName, Size = file.ContentLength, MaxFileSize = this.config.MaxFileSize, MaxAttachmentsSize = this.config.MaxAttachmentsSize, Extensions = this.config.AllowedExtensions }, "mvcForum.Web.AttachmentErrors"));
										}
									}
								}

							}
							else if (newMessage.AttachFile) {
								return RedirectToAction("Attach", "File", new RouteValueDictionary { { "id", post.Id } });
							}
						}

						if (feedback.Any()) {
							TempData.Add("Feedback", feedback.Select(f => new MvcHtmlString(f)));
						}
					}

					// Post done, let's return to the topic!
					// TODO: To the page with the new post!!!!!!!!!!
					return RedirectToRoute("ShowTopic", new RouteValueDictionary { { "id", topic.Id }, { "title", topic.Title.ToSlug() }, { "page", (Int32)Math.Ceiling((Decimal)topic.Posts.Visible(this.config).Count() / config.MessagesPerPage) } });
				}
				else {
					// The user is not allowed to make new posts, let's tell him!
					TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.ForumPosting", new { Name = topic.Forum.Name }));
					// Off to the "no access" page!
					return RedirectToRoute("NoAccess");
				}
			}
			// Let's prepare the model, we need to show it to the user in a bit!
			newMessage.Topic = new TopicViewModel(topic, new MessageViewModel[] { }, 0, config.MessagesPerPage, false, this.config.AllowQuickReply, this.config.AuthorNameSetting);
			newMessage.Path = new Dictionary<string, string>();
			newMessage.CanUpload = topic.Forum.HasAccess(AccessFlag.Upload);
			// Build the breadcrumb path!
			HomeController.BuildPath(topic, newMessage.Path, this.Url);

			// Should we show older posts?
			if (this.config.ShowOldPostsOnReply) {
				// Yeah, so let's get all the posts on the topic, and let's get the latest first!
				IEnumerable<Post> messages = topic.Posts.Visible(this.config).OrderByDescending(m => m.Posted);
				// Should we limit the number of posts?
				if (this.config.PostsOnReply > 0) {
					// Yes, so let's limit the number of posts.
					messages = messages.Take(this.config.PostsOnReply);
				}
				newMessage.Posts = messages.Select(m => new MessageViewModel(m, this.config.AuthorNameSetting)).ToList();
			}

			return View(newMessage);
		}

		[HttpPost]
		[Authorize]
		[NotBanned]
		// TODO: Remove this and get it working with AllowHtml instead!!
		[ValidateInput(false)]
		public ActionResult Quick(QuickReplyViewModel model) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			// Get the parent topic!
			Topic topic = this.GetRepository<Topic>().Read(model.TopicId);

			// Valid post?
			if (ModelState.IsValid) {
				// Can user post?
				if (topic.Forum.HasAccess(AccessFlag.Post)) {
					List<String> feedback = new List<String>();
					Post post = this.postService.Create(
														this.ActiveUser,
														topic,
														String.Format("Re: {0}", topic.Title),
														model.Body,
														Request.UserHostAddress,
														Request.UserAgent,
														Url.RouteUrl("ShowTopic", new { id = topic.Id, area = "forum", title = topic.Title.ToSlug() }),
														feedback,
														null
													);

					if (post != null) {
						if (feedback.Any()) {
							TempData.Add("Feedback", feedback.Select(f => new MvcHtmlString(f)));
						}
					}

					// Post done, let's return to the topic!
					// TODO: To the page with the new post!!!!!!!!!!
					return RedirectToRoute("ShowTopic", new RouteValueDictionary { { "id", topic.Id }, { "title", topic.Title.ToSlug() }, { "page", (Int32)Math.Ceiling((Decimal)topic.Posts.Visible(this.config).Count() / config.MessagesPerPage) } });
				}
				else {
					// The user is not allowed to make new posts, let's tell him!
					TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.ForumPosting", new { Name = topic.Forum.Name }));
					// Off to the "no access" page!
					return RedirectToRoute("NoAccess");
				}
			}
			return RedirectToRoute("ShowTopic", new RouteValueDictionary { { "id", topic.Id }, { "title", topic.Title.ToSlug() }, { "page", (Int32)Math.Ceiling((Decimal)topic.Posts.Visible(this.config).Count() / config.MessagesPerPage) } });
		}
		#endregion

		#region Update
		[Authorize]
		public ActionResult Edit(Int32 id) {
			Post message = this.GetRepository<Post>().Read(id);

			// TODO: First message is topic! Allowed change of status (by moderator)

			// Edit access and the user's own message? Or moderator?
			if ((message.Topic.Forum.HasAccess(AccessFlag.Edit) && this.ActiveUser.Id == message.Author.Id) || message.Topic.Forum.HasAccess(AccessFlag.Moderator)) {
				Dictionary<string, string> path = new Dictionary<string, string>();
				// Create the breadcrumb path!
				HomeController.BuildPath(message.Topic, path, this.Url);
				// Let's show the edit post page to user!
				return View(new UpdateMessageViewModel { TopicId = message.Topic.Id, TopicTitle = message.Topic.Title, Path = path, Body = message.Body, Subject = message.Subject, Id = message.Id, IsModerator = message.Topic.Forum.HasAccess(AccessFlag.Moderator), Flag = message.Flag });
			}

			// The user is not allowed to edit the post, let's tell him!
			TempData.Add("Reason", ForumHelper.GetString("NoAccess.EditPost"));
			// Off to the "no access" page!
			return RedirectToRoute("NoAccess");
		}

		[HttpPost]
		[Authorize]
		[NotBanned]
		// TODO: Remove this and get it working with AllowHtml instead!!
		[ValidateInput(false)]
		public ActionResult Edit(UpdateMessageViewModel messageVM) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			// Let's get the post in question!
			Post post = postRepository.Read(messageVM.Id);

			if (ModelState.IsValid) {
				// What kind of access does the user have on this forum? (given by the topic!)
				AccessFlag flag = post.Topic.Forum.GetAccess();
				PostFlag oldPostFlag = post.Flag;
				TopicFlag oldTopicFlag = post.Topic.Flag;
				// Edit access and the user's own message? Or moderator?
				if (((flag & AccessFlag.Edit) == AccessFlag.Edit && this.ActiveUser.Id == post.Author.Id)) {

					// Is this the author of the original post?
					post.Update(this.ActiveUser, messageVM.Subject.Replace("<", "&gt;"), messageVM.Body);

					// Is this actually the first post in the topic, meaning the topic itself??
					if (post.Position == 0 && post.Topic.Author.Id == this.ActiveUser.Id) {
						// Yes, so let's change the title of the topic then!
						post.Topic.Title = messageVM.Subject.Replace("<", "&gt;");
					}
					// Update the topic.
					// Update the post with the changes!
					this.Context.SaveChanges();

					// TODO: Handle all events async ?!?!?!?
					// Is this actually the first post in the topic, meaning the topic itself??
					if (post.Position == 0 && post.Topic.Author.Id == this.ActiveUser.Id) {
						this.eventPublisher.Publish(new TopicUpdatedEvent { TopicId = post.Topic.Id, UserAgent = Request.UserAgent, ForumId = post.Topic.Forum.Id });
					}
					else {
						this.eventPublisher.Publish(new PostUpdatedEvent { PostId = post.Id, UserAgent = Request.UserAgent, TopicId = post.Topic.Id, ForumId = post.Topic.Forum.Id });
					}
					this.Context.SaveChanges();

					// Back to the show topic page! We're done editing.
					return RedirectToRoute("ShowTopic", new RouteValueDictionary { { "id", post.Topic.Id }, { "title", post.Topic.Title.ToSlug() } });
				}
			}
			// Something wasn't right, so let's make sure the model has all the data needed, so we can show the edit page again!
			messageVM.TopicId = post.Topic.Id;
			messageVM.TopicTitle = post.Topic.Title;
			Dictionary<string, string> path = new Dictionary<string, string>();
			// Build the breadcrumb path again!
			HomeController.BuildPath(post.Topic, path, this.Url);

			return View(messageVM);
		}
		#endregion

		#region Moderate
		[Authorize]
		public ActionResult Moderate(Int32 id) {
			Post post = this.GetRepository<Post>().Read(id);
			if (post.Topic.Forum.HasAccess(AccessFlag.Moderator)) {
				Dictionary<String, String> path = new Dictionary<String, String>();
				// Create the breadcrumb path!
				HomeController.BuildPath(post.Topic, path, this.Url);

				return View(new UpdateMessageViewModel { TopicId = post.TopicId, TopicTitle = post.Topic.Title, Id = post.Id, Subject = post.Subject, Body = post.Body, Flag = post.Flag, Path = path, IsModerator = post.Topic.Forum.HasAccess(AccessFlag.Moderator), Reason = post.EditReason });
			}

			// The user is not allowed to edit the topic, let's tell him!
			TempData.Add("Reason", ForumHelper.GetString("NoAccess.ModeratorForum", new { Name = post.Topic.Forum.Name }));
			// Off to the "no access" page!
			return RedirectToRoute("NoAccess");
		}

		[Authorize]
		[HttpPost]
		// TODO: Remove this and get it working with AllowHtml instead!!
		[ValidateInput(false)]
		public ActionResult Moderate(UpdateMessageViewModel model) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			// Let's get the post in question!
			Post post = postRepository.Read(model.Id);

			if (ModelState.IsValid) {
				AccessFlag flag = post.Topic.Forum.GetAccess();
				PostFlag oldPostFlag = post.Flag;
				TopicFlag oldTopicFlag = post.Topic.Flag;
				if ((flag & AccessFlag.Moderator) == AccessFlag.Moderator) {
					post.Update(this.ActiveUser, model.Subject.Replace("<", "&gt;"), model.Body, model.Reason);
					//post.RemoveFlag(post.Flag);
					post.SetFlag(model.Flag);

					if (post.Flag == PostFlag.None && post.Topic.Posts.Visible(this.config).OrderByDescending(p=>p.Posted).FirstOrDefault() == post) {
						post.Topic.LastPost = post;
						post.Topic.LastPostAuthor = post.Author;
						post.Topic.LastPosted = post.Posted;
						post.Topic.LastPostUsername = post.AuthorName;
					}
					this.context.SaveChanges();

					if (oldPostFlag != post.Flag) {
						this.eventPublisher.Publish(new PostFlagUpdatedEvent { PostId = post.Id, OriginalFlag = oldPostFlag, TopicRelativeURL = Url.RouteUrl("ShowTopic", new { id = post.Topic.Id, area = "forum", title = post.Topic.Title.ToSlug() }) });
					}
					else {
						this.eventPublisher.Publish(new PostUpdatedEvent { PostId = post.Id, UserAgent = Request.UserAgent, TopicId = post.Topic.Id, ForumId = post.Topic.Forum.Id });
					}

					return RedirectToAction("index", "moderate", new RouteValueDictionary { { "id", post.Topic.Forum.Id }, { "area", "forum" } });
				}
				else {
					// The user is not allowed to edit the topic, let's tell him!
					TempData.Add("Reason", ForumHelper.GetString("NoAccess.ModeratorForum", new { Name = post.Topic.Forum.Name }));
					// Off to the "no access" page!
					return RedirectToRoute("NoAccess");
				}
			}

			// Something wasn't right, so let's make sure the model has all the data needed, so we can show the moderate page again!
			model.TopicId = post.Topic.Id;
			model.TopicTitle = post.Topic.Title;
			Dictionary<String, String> path = new Dictionary<String, String>();
			// Build the breadcrumb path again!
			HomeController.BuildPath(post.Topic, path, this.Url);

			return View(model);
		}
		#endregion

		#region Delete
		/// <summary>
		/// Action used to show a "confirm delete" view.
		/// </summary>
		/// <param name="id">The id of the post that should be deleted.</param>
		/// <returns></returns>
		[Authorize]
		public ActionResult Delete(Int32 id) {
			// Get the post
			Post post = this.GetRepository<Post>().Read(id);

			// Can the user delete this post?
			if (this.CanDeletePost(post)) {
				Dictionary<String, String> path = new Dictionary<String, String>();
				// Let's build the breadcrumb path.
				HomeController.BuildPath(post.Topic, path, this.Url);

				// Show the delete page.
				return View(new DeleteMessageViewModel { Id = post.Id, TopicId = post.Topic.Id, TopicTitle = post.Topic.Title, Path = path, Subject = post.Subject });
			}

			// The user is not allowed to delete the page.
			TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.MessageDelete", new { Subject = post.Subject }));
			// Show the "no access" page.
			return RedirectToRoute("NoAccess");
		}

		/// <summary>
		/// Method use to determine whether of not the active user has delete access to the given post.
		/// </summary>
		/// <param name="post">The post in question.</param>
		/// <returns></returns>
		[NonAction]
		private Boolean CanDeletePost(Post post) {
			// Get the parent forum.
			var forum = post.Topic.Forum;
			// What kind of access does the user have?
			var flag = forum.GetAccess();

			// Moderator? Or author with Delete access.
			if ((flag & AccessFlag.Moderator) == AccessFlag.Moderator || ((flag & AccessFlag.Delete) == AccessFlag.Delete && this.ActiveUser.Id == post.Author.Id)) {
				// Yeah, delete away!
				return true;
			}
			// No!
			return false;
		}

		/// <summary>
		/// Method that deleted the post given.
		/// </summary>
		/// <param name="model">Model containing information about the post to be deleted.</param>
		/// <returns></returns>
		[Authorize]
		[HttpPost]
		[NotBanned]
		public ActionResult Delete(DeleteMessageViewModel model) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			Post post = postRepository.Read(model.Id);
			PostFlag originalFlag = post.Flag;
			if (post != null) {
				Topic topic = post.Topic;
				if (ModelState.IsValid) {
					if (post.Position == 0) {
						// TODO: Topic, what to do !???
						throw new NotImplementedException("Deleting a topic!?");
					}
					if (model.Delete && this.CanDeletePost(post)) {
						post.Delete(this.ActiveUser, model.Reason);
						this.Context.SaveChanges();

						this.eventPublisher.Publish(new PostFlagUpdatedEvent { PostId = post.Id, OriginalFlag = originalFlag, TopicRelativeURL = Url.RouteUrl("ShowTopic", new { id = topic.Id, area = "forum", title = topic.Title.ToSlug() }), });

						this.Context.SaveChanges();

						return RedirectToRoute("ShowTopic", new RouteValueDictionary { { "id", topic.Id }, { "title", topic.Title.ToSlug() } });
					}
				}

				Dictionary<string, string> path = new Dictionary<string, string>();
				HomeController.BuildPath(topic, path, this.Url);
				model.Path = path;
				model.TopicId = topic.Id;
				model.TopicTitle = topic.Title;
				model.Subject = post.Subject;
			}
			return View(model);
		}

		[Authorize]
		public ActionResult Undelete(Int32 id) {
			// Get the post
			Post post = this.GetRepository<Post>().Read(id);

			// Can the user undelete this post?
			if (post.Topic.Forum.HasAccess(AccessFlag.Moderator) && post.Flag == PostFlag.Deleted) {
				Dictionary<String, String> path = new Dictionary<String, String>();
				// Let's build the breadcrumb path.
				HomeController.BuildPath(post.Topic, path, this.Url);

				// Show the delete page.
				return View(new DeleteMessageViewModel { Id = post.Id, Delete = true, Reason = post.DeleteReason, TopicId = post.Topic.Id, TopicTitle = post.Topic.Title, Path = path, Subject = post.Subject });
			}

			// The user is not allowed to undelete the post.
			TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.MessageUndelete", new { Subject = post.Subject }));
			// Show the "no access" page.
			return RedirectToRoute("NoAccess");
		}

		[Authorize]
		[HttpPost]
		[NotBanned]
		public ActionResult Undelete(DeleteMessageViewModel model) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			Post post = postRepository.Read(model.Id);
			PostFlag originalFlag = post.Flag;
			if (post != null) {
				Topic topic = post.Topic;
				if (ModelState.IsValid) {
					if (post.Position == 0) {
						// TODO: Topic, what to do !???
						throw new NotImplementedException("Deleting a topic!?");
					}
					if (!model.Delete && post.Topic.Forum.HasAccess(AccessFlag.Moderator)) {
						post.Undelete(this.ActiveUser, model.Reason);
						this.Context.SaveChanges();

						this.eventPublisher.Publish(new PostFlagUpdatedEvent { PostId = post.Id, OriginalFlag = originalFlag, TopicRelativeURL = Url.RouteUrl("ShowTopic", new { id = topic.Id, area = "forum", title = topic.Title.ToSlug() }), });

						this.Context.SaveChanges();

						return RedirectToAction("topic", "moderate", new RouteValueDictionary { { "id", topic.Id } });
					}
				}

				Dictionary<string, string> path = new Dictionary<string, string>();
				HomeController.BuildPath(topic, path, this.Url);
				model.Path = path;
				model.TopicId = topic.Id;
				model.TopicTitle = topic.Title;
				model.Subject = post.Subject;
			}
			return View(model);
		}
		#endregion

		#region Report
		[Authorize]
		public ActionResult Report(Int32 id) {
			// Get the post.
			Post post = this.GetRepository<Post>().Read(id);
			// Does the user have read access to the post/forum ?
			if (post.Topic.Forum.HasAccess(AccessFlag.Read)) {
				// Create the model.
				ReportMessageViewModel model = new ReportMessageViewModel { Subject = post.Subject, Id = post.Id, TopicId = post.Topic.Id, TopicTitle = post.Topic.Title };
				Dictionary<string, string> path = new Dictionary<string, string>();
				// Build the breadcrumb path.
				HomeController.BuildPath(post.Topic, path, this.Url);
				model.Path = path;

				// Show it to the user.
				return View(model);
			}

			// Ups, the user is not allowed to read the post, let him know!
			TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.Forum", new { Name = post.Topic.Forum.Name }));
			// Let's go to the "no access" page!
			return RedirectToRoute("NoAccess");
		}

		[Authorize]
		[HttpPost]
		public ActionResult Report(ReportMessageViewModel model) {
			IRepository<Post> postRepository = this.GetRepository<Post>();
			// Get the post.
			Post post = postRepository.Read(model.Id);
			// Does the user have read access to this post/forum?
			if (post.Topic.Forum.HasAccess(AccessFlag.Read)) {
				// Was all required fields ok?
				if (ModelState.IsValid) {
					IRepository<PostReport> postReportRepository = this.GetRepository<PostReport>();
					// Create the report!
					// TODO: Feedback!?!??!?!
					PostReport report = new PostReport(post, model.Reason, this.ActiveUser, false);
					postReportRepository.Create(report);

					this.Context.SaveChanges();

					// Report done, let's return to the topic!
					return RedirectToRoute("ShowTopic", new RouteValueDictionary { { "id", post.Topic.Id }, { "title", post.Topic.Title.ToSlug() } });
				}
				// Let's show the report page again!
				return View(model);
			}

			// Ups, the user is not allowed to read the post, let him know!
			TempData.Add("Reason", ForumHelper.GetString<mvcForum.Web.ForumConfigurator>("NoAccess.Forum", new { Name = post.Topic.Forum.Name }));
			// Let's go to the "no access" page!
			return RedirectToRoute("NoAccess");
		}
		#endregion
	}
}